package com.ma.chapter8.aqs;

import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.AbstractQueuedSynchronizer;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;

import static com.ma.util.Sleeper.sleep;

/**
 * @ClassName TestAqs
 * @Author: mayongqiang
 * @DATE 2022/3/23 20:23
 * @Description: AQS 自定义实现
 */
@Slf4j(topic = "m.TestAqs")
public class TestAqs {

    public static void main(String[] args) {
        MyLock myLock = new MyLock();
        new Thread(() -> {
            myLock.lock();
            try {
                log.debug("t1加锁");
                sleep(1);
            } finally {
                myLock.unlock();
                log.debug("t1解锁");
            }
        }, "t1").start();
        new Thread(() -> {
            myLock.lock();
            try {
                log.debug("t2加锁");
            } finally {
                myLock.unlock();
                log.debug("t2解锁");
            }
        }, "t2").start();
    }

}

/* 自定义锁  -->  不可重入锁 */
class MyLock implements Lock {

    private MySync sync = new MySync();

    /*
        加锁 不成功会进入等待队列等待
     */
    @Override
    public void lock() {
        sync.acquire(1);

    }

    /*
        加锁 可打断
     */
    @Override
    public void lockInterruptibly() throws InterruptedException {
        sync.acquireInterruptibly(1);
    }

    /*
         尝试枷锁  一次
     */
    @Override
    public boolean tryLock() {
        return sync.tryAcquire(1);
    }

    /*
         带超时时间的尝试枷锁  一次
     */
    @Override
    public boolean tryLock(long time, TimeUnit unit) throws InterruptedException {
        return sync.tryAcquireNanos(1, unit.toNanos(time));
    }

    /*
        解锁
     */
    @Override
    public void unlock() {
        sync.release(1);

    }

    @Override
    public Condition newCondition() {
        return null;
    }


    /**
     * AQS : AbstractQueuedSynchronizer 是阻塞式锁和相关的同步器工具的框架
     * 同步器类
     */
    class MySync extends AbstractQueuedSynchronizer {
        /*

         */
        @Override
        protected boolean tryAcquire(int arg) {
            if (compareAndSetState(0, 1)) {
                //加上了锁 , 并设置owner为当前线程
                setExclusiveOwnerThread(Thread.currentThread());
                return true;
            }
            return false;
        }

        @Override
        protected boolean tryRelease(int arg) {
            setExclusiveOwnerThread(null);
            setState(0);
            return true;
        }

        //是否持有独占锁
        @Override
        protected boolean isHeldExclusively() {
            return getState() == 1;
        }

        public Condition newCondition() {
            return new ConditionObject();
        }
    }

}
